﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Security;
using Castle.MonoRail.Framework;
using StateTheater.Helpers;
using StateTheater.Models;
using StateTheaterDataModel;
using StateTheater;

namespace StateTheater.Controllers
{

	/// <summary>
	/// WSController - "Web Service" provider.
	/// Supplies data instead of web pages.  Mostly JSON.
	/// </summary>
	[Rescue("jsonerror")]
	public class WSController : SmartDispatcherController
	{
		public StateTheaterDataContext db { get; set; }
		public SnitzUtil MemberHelper { get; set; }

		readonly Status OK = new Status("OK");
		readonly Status BAD = new Status("BAD");



		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] MemberByUsername(string q, int limit)
		{
			var mems = from fm in db.FORUM_MEMBERs
					where fm.M_NAME.StartsWith(q)
					select new SelectList(fm.M_NAME + " ("+ fm.M_FIRSTNAME + " " + fm.M_LASTNAME + ")", fm.MEMBER_ID);
			return mems.Take(limit).ToArray();
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] MemberByUsername(string term)
		{
			return MemberByUsername(term, 10);
		}

		public void FindMemberText(string term)
		{
			int limit = 10;
			var mems = (from fm in db.FORUM_MEMBERs
					   where fm.M_NAME.StartsWith(term)
						select new SelectList(fm.M_NAME + " (" + fm.M_FIRSTNAME + " " + fm.M_LASTNAME + ")", fm.MEMBER_ID)).Take(limit);
			OutputList(mems, term);
		}

		private void OutputList(IQueryable<SelectList> query, string partial)
		{
			if (string.IsNullOrEmpty(partial))
			{
				RenderText("");
			}
			else
			{
				foreach (var p in query)
				{
					RenderText(p.id + '|' + p.label + Environment.NewLine);
				}
			}
		}


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] FindTroupe(string term)
		{
			return FindTroupe(term, 10);
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public SelectList[] FindTroupe(string term, int limit)
		{
			if (string.IsNullOrEmpty(term))
			{
				return new SelectList[0];
			}
			var l = (from p in db.Troupes
					where p.Name.Contains(term)
					orderby p.Name
					select new SelectList(p.Name, p.TroupeID))
					.Take(limit).ToArray();
			return l;
		}

		[Rescue(typeof(XmlRescueController))]
		[return: XmlReturnBinder]
		public SelectList[]  FindTroupeXML(string term, int limit)
		{
			return FindTroupe(term, limit);
		}


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status AddCredit(int prodid, int person, int credit, int which)
		{
			if (prodid == 0 || person == 0 || credit == 0)
				return BAD;

			db.Log = new Castle.MonoRail.Framework.Internal.ProperyBagTextWriter("log", PropertyBag);
			switch (which)
			{
				case 1:
					ProductionCredit pc = new ProductionCredit();
					pc.ProductionID = prodid;
					pc.PersonID = person;
					pc.CreditID = credit;
					db.ProductionCredits.InsertOnSubmit(pc);
					break;

				case 2:
					PlayCredit plc = new PlayCredit();
					plc.CreditID = credit;
					plc.PersonID = person;
					plc.PlayID = db.Productions.First(pr => pr.ProductionID == prodid).PlayID;
					db.PlayCredits.InsertOnSubmit(plc);
					break;
				default:
					return BAD;
			}

			db.SubmitChanges();
			return OK;
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<PhotoItem> GetPhotosJson(int id)
		{
			return new jqGridPacket<PhotoItem> (ShowController.GetPhotoList(db, id));
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status DeletePhotoJson(int id, string oper)
		{
			if (oper == "del")
			{
				var photo = db.Photos.FirstOrDefault(ph=>ph.PK == id);
				if (photo != null)
				{
					var prod = photo.Production;
					db.Photos.DeleteOnSubmit(photo);
					var filename = Path.Combine(ShowController.StillsFolder(this), photo.Filename);
					File.Delete(filename);
					db.SubmitChanges();

					if (!db.Photos.Any(ph => ph.productionID == prod.ProductionID))
					{
						prod.HasPhotos = false;
						db.SubmitChanges();
					}
					return Status.OK;
				}
			}

			return Status.BAD;
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status EditPhotoJson(string oper, int id, string Caption)
		{
			if (oper == "edit")
			{
				var photo = db.Photos.FirstOrDefault(ph => ph.PK == id);
				if (photo != null)
				{
					photo.Caption = Caption;
					db.SubmitChanges();
					return Status.OK;
				}
			}

			return Status.BAD;
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status NewPhoto(int prodid, string Caption, HttpPostedFile uploadedPhoto)
		{
			var prod = db.Productions.FirstOrDefault(pr => pr.ProductionID == prodid);
			if (prod == null)
				return Status.BAD;

			prod.HasPhotos = true;

			const string PhotoFormat = "P{0:0000}-{1:0000}.jpg";

			Bitmap image = new Bitmap(uploadedPhoto.InputStream);
			image = Util.ResizeImage(image, 600, 400);

			var highest = db.Photos.Where(ph => ph.productionID == prodid).Max(ph=>ph.Filename);
			var seq = highest == null ? 1 : Int32.Parse(highest.Substring(6, 4)) + 1;

			string filename = String.Format(PhotoFormat, prodid, seq);

			image.Save(Path.Combine(ShowController.StillsFolder(this), filename), ImageFormat.Jpeg);
			var photo = new Photo();
			photo.Filename = filename;
			photo.productionID = prodid;
			photo.Caption = Caption;
			db.Photos.InsertOnSubmit(photo);
			db.SubmitChanges();
			this.Response.ContentType = "text/json";
			return Status.OK;
		}

		// ----- Utility 


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<TraceRtLine> TraceRt(string dest)
		{
			return new jqGridPacket<TraceRtLine>(Util.TraceRoute(dest));
		}




		// ----- FORUM_MEMBER_PENDING


		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public jqGridPacket<PendingMemberDetail> GetPendingMembers()
		{
			var paging = new jqGridPager(this.Request.Params);
			var q = from mp in db.FORUM_MEMBERS_PENDINGs
					select new PendingMemberDetail
					{
						MemberId = mp.MEMBER_ID,
						Name = mp.M_NAME,
						Email = mp.M_EMAIL,
						IPAddress = mp.M_IP,
						Date = mp.M_DATE
					};


			IOrderedQueryable<PendingMemberDetail> pending;
			switch (paging.SortBy + '-' + paging.SortDirect)
			{
				case "Name-asc":
					pending = q.OrderBy(pm => pm.Name);
					break;

				case "Name-desc":
					pending = q.OrderByDescending(pm => pm.Name);
					break;

				case "Email-asc":
					pending = q.OrderBy(pm => pm.Email);
					break;

				case "Email-desc":
					pending = q.OrderByDescending(pm => pm.Email);
					break;

				case "IPAddress-asc":
					pending = q.OrderBy(pm => pm.IPAddress);
					break;

				case "IPAddress-desc":
					pending = q.OrderByDescending(pm => pm.IPAddress);
					break;

				case "Date-asc":
				default:
					pending = q.OrderBy(pm => pm.Date);
					break;

				case "Date-desc":
					pending = q.OrderByDescending(pm => pm.Date);
					break;
			}
			/*
			var pendingPage = paging.AddPaging(pending).ToList();
			pendingPage.ForEach(pmd => pmd.Days = (int)(DateTime.Today - DateTime.ParseExact(pmd.Date, "yyyyMMddHHmmss", null)).TotalDays);
			var page = new jqGridPacket<PendingMemberDetail>(pendingPage);
			//page.page = paging.Page;
			//page.records = db.FORUM_MEMBERS_PENDINGs.Count();
			//page.total = (page.records + paging.Rows - 1) / paging.Rows;
			paging.SetResponse(page, db.FORUM_MEMBERS_PENDINGs.Count());
			return page;
			 * */
//			var pendingPage = paging.PackageResponse(pending, db.FORUM_MEMBERS_PENDINGs.Count());
			var pendingPage = paging.PackageResponse(pending);
			foreach (var pmd in pendingPage.rows) { pmd.Days = (int)(DateTime.Today - DateTime.ParseExact(pmd.Date, "yyyyMMddHHmmss", null)).TotalDays; };
			return pendingPage;
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status DeletePendingMember(string oper, int id)
		{
			if (oper == "del")
			{
				var mem = db.FORUM_MEMBERS_PENDINGs.Where(pm => pm.MEMBER_ID == id).FirstOrDefault();
				if (mem == null)
					return BAD;
				db.FORUM_MEMBERS_PENDINGs.DeleteOnSubmit(mem);
				db.SubmitChanges();
				return OK;
			}
			return BAD;
		}

		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status ActivatePendingMember(int id)
		{
			var member = MemberHelper.ActivatePendingMember(id);
			if (member != null)
			{
				AdminController.MailMessage(member, this, "MemberActivated", PropertyBag);
				return Status.OK;
			}
			else
				return Status.BAD;
		}



		[return: JSONReturnBinder]
		[Rescue(typeof(JsonRescueController))]
		public Status ResendEmailToPendingMember(int id)
		{
			var pending = db.FORUM_MEMBERS_PENDINGs.FirstOrDefault(mp => mp.MEMBER_ID == id);
			if (pending == null)
				return BAD;

			FORUM_MEMBER member = MemberHelper.CopyPending2Member(pending);
			AdminController.MailMessage(member, this, "MemberActivate", PropertyBag);
			return OK;
		}
	}
}
